package risk.control.application.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class ImageCompressor {

    /**
     * 将图片byte[]压缩到指定大小以下
     *
     * @param originalData 原始图片数据
     * @param maxSize      目标最大大小(单位:字节)
     * @param format       压缩格式(Bitmap.CompressFormat.JPEG/PNG/WEBP)
     * @return 压缩后的byte[]
     * @throws IOException
     */
    public static byte[] compressToTargetSize(byte[] originalData, long maxSize, Bitmap.CompressFormat format) {
        // 1. 解码原始图片并获取尺寸信息
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(originalData, 0, originalData.length, options);

        // 2. 计算初始采样率
        int inSampleSize = calculateInitialSampleSize(options, maxSize);
        options.inJustDecodeBounds = false;
        options.inSampleSize = inSampleSize;

        // 3. 解码为Bitmap
        Bitmap bitmap = BitmapFactory.decodeByteArray(originalData, 0, originalData.length, options);

        // 4. 质量压缩
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int quality = 90; // 初始质量
        do {
            outputStream.reset(); // 清空流
            bitmap.compress(format, quality, outputStream);
            // 检查是否达到目标大小或达到最低质量限制
            if (outputStream.size() <= maxSize || quality <= 10) {
                break;
            }
            // 未达到则降低质量继续尝试
            quality -= 10;
        } while (true);
        bitmap.recycle();
        return outputStream.toByteArray();
    }

    public static Single<byte[]> compressPic(byte[] originalData, long maxSize, Bitmap.CompressFormat format) {
        return Single.fromCallable(() -> {
                    // 1. 解码原始图片并获取尺寸信息
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true;
                    BitmapFactory.decodeByteArray(originalData, 0, originalData.length, options);

                    // 2. 计算初始采样率
                    int inSampleSize = calculateInitialSampleSize(options, maxSize);
                    options.inJustDecodeBounds = false;
                    options.inSampleSize = inSampleSize;

                    // 3. 解码为Bitmap
                    Bitmap bitmap = BitmapFactory.decodeByteArray(originalData, 0, originalData.length, options);

                    // 4. 质量压缩
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    int quality = 90; // 初始质量
                    do {
                        outputStream.reset(); // 清空流
                        bitmap.compress(format, quality, outputStream);
                        // 检查是否达到目标大小或达到最低质量限制
                        if (outputStream.size() <= maxSize || quality <= 10) {
                            break;
                        }
                        // 未达到则降低质量继续尝试
                        quality -= 10;
                    } while (true);
                    bitmap.recycle();
                    return outputStream.toByteArray();
                }).subscribeOn(Schedulers.io())//io
                .observeOn(AndroidSchedulers.mainThread());//主线程
    }

    /**
     * 计算初始采样率
     */
    private static int calculateInitialSampleSize(BitmapFactory.Options options, long maxSize) {
        // 原始图片像素总数
        long totalPixels = (long) options.outWidth * options.outHeight;

        // 估算原始图片大小(假设每个像素占4字节)
        long originalSize = totalPixels * 4;

        // 计算初始采样率(开平方近似)
        int sampleSize = (int) Math.sqrt((double) originalSize / maxSize);

        // 确保采样率是2的幂次(系统要求)
        sampleSize = Math.max(1, Integer.highestOneBit(sampleSize));

        return sampleSize;
    }

    /**
     * 更精确的压缩方法(包含尺寸和质量双重压缩)
     */
    public static byte[] preciseCompress(byte[] originalData, long maxSize, Bitmap.CompressFormat format) throws IOException {
        Bitmap bitmap = BitmapFactory.decodeByteArray(originalData, 0, originalData.length);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int quality = 90;
        float scale = 1.0f;

        do {
            outputStream.reset();

            // 如果需要缩放
            if (scale < 1.0f) {
                Matrix matrix = new Matrix();
                matrix.postScale(scale, scale);
                Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                scaledBitmap.compress(format, quality, outputStream);
                scaledBitmap.recycle();
            } else {
                bitmap.compress(format, quality, outputStream);
            }

            // 检查是否达标
            if (outputStream.size() <= maxSize || (quality <= 20 && scale <= 0.25f)) {
                break;
            }

            // 调整参数
            if (quality > 20) {
                quality -= 10; // 优先降低质量
            } else {
                scale *= 0.8f; // 质量降到20后开始缩小尺寸
            }
        } while (true);

        bitmap.recycle();
        return outputStream.toByteArray();
    }
}
